"use strict"
const crypto = require('crypto');

/*
    微信小游戏
    文档地址：https://developers.weixin.qq.com/minigame/dev/api/midas-payment/midasPay.html
    微信DOS: https://developers.weixin.qq.com/doc/
 */


const login_url = {
    "sandbox":"https://api.weixin.qq.com",
    "production":"https://api.weixin.qq.com",
}

const payment_url = "https://api.weixin.qq.com";

const access_url = "https://api.weixin.qq.com/cgi-bin/token";

exports.format = {
    "id":'midas',
    "name":"微信小游戏、小程序[米大师支付]",
    "fields":{
        "appid" :{'type':'string','val':'','name':"login appid"},
        "secret" :{'type':'string','val':'','name':"login secret"},
        "offerid" :{'type':'string','val':'','name':"米大师支付offer_id"},
        "paysecret" :{'type':'string','val':'','name':"米大师支付secret"},
    }
}
//登录与认证TOKEN
exports.login = function () {
    let code = this.get("code")
    if(!code){
        return this.error("code empty");
    }
    if(!this.opensdk.setting || !this.opensdk.setting.appid || !this.opensdk.setting.secret){
        return this.error("opensdk.setting empty");
    }
    let api = "/sns/jscode2session";
    let host = (this.opensdk.status > 0 ? login_url.production : login_url.sandbox) + api;
    let args = {"appid":this.opensdk.setting.appid,"secret":this.opensdk.setting.secret,"js_code":code,"grant_type":"authorization_code"};

    // let data = null;
    // let url = host + '?' + querystring.stringify(args);
    // console.log("url",url)

    return this.library("request/get", host, args).then(ret=>{
        if( ret["errcode"] ){
            return this.error(`${ret["errmsg"]}[${ret["errmsg"]}]` )
        }
        //let expires = Date.now() + body["expires_in"] * 1000;
        return {"openid":ret["openid"],"token":{"unionid":ret["unionid"]||'',"session":ret["session_key"]}}
    })
}

/**
 * @name orderCreate
 * 创建订单
 */
exports.orderCreate = function(config){
    let data = {};
    data["rmb"] = config['rmb'];
    data["attach"] = [config['attach'],config['rmb']].join('|');
    data["orderid"] = config['orderid'];
    return data;
}

/**
 * @name orderNotify
 * 回调发货
 * 此步骤会去米大师扣除游戏币，如果游戏币不足，前端再去充值，然后在回到此步骤
 */

exports.orderNotify = function(){
    let access = this.get("access",'string');
    let attach = this.get("attach",'string');
    let orderid = this.get("orderid",'string');
    if( !access){
        return Promise.reject('access empty')
    }
    if( !attach || attach.indexOf("|") <0  ){
        return Promise.reject("attach_empty")
    }
    if( !orderid){
        return Promise.reject('orderid_empty')
    }
    let arr = attach.split("|");
    if(arr.length !== 4){
        return Promise.reject('attach error')
    }
    let rmb = parseInt(arr[3]);
    if(!rmb){
        return Promise.reject('attach rmb empty')
    }

    let openid = this.model.branch("openid",this.branch);
    return openid.verify(access).then(ret=>{
        ret['sid'] = parseInt(arr[1]);
        ret['rmb'] = rmb;
        ret['orderid'] = orderid;
        return sub_rmb_from_weixin.call(this,ret);
    }).then(()=>{
        return {"attach":attach,"orderid":orderid}
    })
}


//获取米大师access token
function get_access_token(){
    let query = {"grant_type":"client_credential","appid":this.opensdk.setting.appid,"secret":this.opensdk.setting.secret}
    return this.library("request/get", access_url, query).then(ret=>{
        if( ret["errcode"] ){
            return this.error("get_access_token_error",`${ret["errmsg"]}[${ret["errmsg"]}]` );
        }
        return {"access":ret["access_token"],"expire":ret["expires_in"]}
    })
}




function sub_rmb_from_weixin(args){
    //console.log("========================================");
    let tokenKey = this.opensdk['_id'];
    let tokenModel = mvc.model.redis('token',this.branch);
    return tokenModel.get(tokenKey).then(ret=>{
        if(ret){
            return ret;
        }
        //获取新的token
        return tokenModel.lock(tokenKey).then(ret=>{
            if(ret.length > 0){
                return this.error("tryAgain",5);
            }
            else {
                return get_access_token.call(this);
            }
        }).then(ret=>{
            return tokenModel.set(tokenKey,ret['access'],ret['expire']).then(ret=>ret['access'])
        })
    }).then(access=>{
        let api = this.opensdk.status > 0 ? "/cgi-bin/midas/pay" : "/cgi-bin/midas/sandbox/pay";
        let url = `${payment_url}${api}?access_token=${access}`;


        let method = "POST";

        let query = {
            "openid":args.openid,
            "appid":this.opensdk.setting.appid,
            "offer_id":this.opensdk.setting.offerid,
            "ts":Math.floor(Date.now() / 1000),
            "zone_id":String(args.sid),
            "pf":"android",
        }

        query['amt'] = (args.rmb) * 10;     //微信虚拟货币单位1元 = 10个
        query['bill_no'] = args.orderid;

        query['sig'] =get_midas_sign(method,api,this.opensdk.setting.paysecret,query,'secret' );

        query['access_token'] = access;
        query['mp_sig'] =get_midas_sign(method,api,args.token.session,query,'session_key' );
        return this.library("request/post", url, query);
    }).then(ret=>{
        if( ret["errcode"] ){
            return this.error("weixin_subrmb_error",ret["errcode"],ret["errmsg"] )
        }
    })
}




function get_midas_sign(method,api,secret,params,secret_name){
    let arr = Object.keys(params);
    arr.sort();
    let oa = [];
    for (let k of arr){
        oa.push(k+'='+params[k])
    }
    oa.push('org_loc='+api)
    oa.push('method='+method)
    oa.push(secret_name + '='+secret)


    let str = oa.join("&")
    //console.log("get_midas_sign:",str)
    //console.log("-----------------------------------");
    //let es = encodeURIComponent(os)
    //let rs = [method,encodeURIComponent(api),es ].join("&")

    return crypto.createHmac('sha256', secret ).update(str).digest().toString('hex');
}


